package com.easyseata.common.interceptor.handler;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Optional;


import com.easyseata.common.interceptor.InvocationWrapper;
import com.easyseata.common.interceptor.NestInterceptorHandlerWrapper;
import com.easyseata.common.util.CollectionUtils;


public abstract class AbstractProxyInvocationHandler implements ProxyInvocationHandler {

    protected abstract Object doInvoke(InvocationWrapper invocation) throws Throwable;

    protected int order = Integer.MAX_VALUE;

    protected ProxyInvocationHandler nextInvocationHandlerChain;

    @Override
    public Object invoke(InvocationWrapper invocation) throws Throwable {
        if (CollectionUtils.isNotEmpty(getMethodsToProxy()) && !getMethodsToProxy().contains(invocation.getMethod().getName())) {
            return invocation.proceed();
        }
        if (nextInvocationHandlerChain != null) {
            invocation = new NestInterceptorHandlerWrapper(nextInvocationHandlerChain, invocation);
        }
        return doInvoke(invocation);
    }

    public  <T extends Annotation> T getAnnotation(Method method, Class<?> targetClass, Class<T> annotationClass) {
        return Optional.ofNullable(method).map(m -> m.getAnnotation(annotationClass))
            .orElse(Optional.ofNullable(targetClass).map(t -> t.getAnnotation(annotationClass)).orElse(null));
    }

    @Override
    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public int getOrder() {
        return this.order;
    }

    @Override
    public void setNextProxyInvocationHandler(ProxyInvocationHandler next) {
        this.nextInvocationHandlerChain = next;
    }
}
